package cn.itcast.account.service.impl;

import cn.itcast.account.entity.AccountFreeze;
import cn.itcast.account.mapper.AccountFreezeMapper;
import cn.itcast.account.mapper.AccountMapper;
import cn.itcast.account.service.AccountTccService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class AccountTccServiceImpl implements AccountTccService {

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private AccountFreezeMapper freezeMapper;

    /**
     * 扣款
     *
     * @param userId 用户id
     * @param money  扣款金额
     */
    @Override
    @Transactional
    public void deduct(String userId, int money) {
        log.info("TCC扣减金额开始执行");
        // 获取事务id
        String xid = RootContext.getXID();

        // 业务悬挂判定
        AccountFreeze cancelFreeze = freezeMapper.selectById(xid);
        if (cancelFreeze != null) {
            // 拒绝业务，直接返回
            return;
        }

        // 扣減可用余额
        accountMapper.deduct(userId, money);
        // 冻结金额,记录事务状态
        AccountFreeze accountFreeze = new AccountFreeze();
        accountFreeze.setUserId(userId);
        accountFreeze.setFreezeMoney(money);
        accountFreeze.setState(AccountFreeze.State.TRY);
        accountFreeze.setXid(xid);
        freezeMapper.insert(accountFreeze);
    }

    /**
     * 确认扣款
     *
     * @param businessActionContext
     */
    @Override
    public boolean confirm(BusinessActionContext businessActionContext) {
        // 获取事务id,删除冻结记录
        String xid = businessActionContext.getXid();
        int i = freezeMapper.deleteById(xid);
        return i == 1;
    }

    /**
     * 取消扣款
     *
     * @param businessActionContext
     */
    @Override
    public boolean cancel(BusinessActionContext businessActionContext) {
        log.info("TCC取消扣款开始执行");
        // 0.查询冻结记录
        String xid = businessActionContext.getXid();
        AccountFreeze freeze = freezeMapper.selectById(xid);

        // 空回滚
        if (freeze == null) {
            // 冻结金额,记录事务状态
            String userId = businessActionContext.getActionContext("userId").toString();
            AccountFreeze accountFreeze = new AccountFreeze();
            accountFreeze.setUserId(userId);
            accountFreeze.setFreezeMoney(0);
            accountFreeze.setState(AccountFreeze.State.CANCEL);
            accountFreeze.setXid(xid);
            freezeMapper.insert(accountFreeze);
            return true;
        }

        // 判定幂等，防止cancel超时重复执行重复插入数据
        if (freeze.getState() == AccountFreeze.State.CANCEL) {
            // 已经处理过一次cancel了
            return true;
        }

        // 1.恢复可用余额
        accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney());
        // 2.将冻结金额清零，状态改为CANCEL
        freeze.setFreezeMoney(0);
        freeze.setState(AccountFreeze.State.CANCEL);
        int count = freezeMapper.updateById(freeze);
        return count == 1;
    }
}
